#include <set>

#include <QList>
#include <QRemoteObjectHost>
#include <QThread>
#include <QIODevice>

#include <QtCore/private/QObject_p.h>
#include <private/qobject_p.h>

#include "../QRO_p.h"
#include "../QROHost.h"
#include "../QRemoteObject2Meta_P.h"
#include "../QRemoteItem.h"
#include "../QROClient.h"
#include "../QROHostDelegate.h"

#include <rep_RemoteInterface_source.h>

//私有公共数据定义

//对象状态信息
struct ObjectData{
    ObjectID id;
    QList<ObjectID> registerList;//仅头节点该数组有值，当创建头节点时，按照注册顺序将子节点一一放入到该列表中
    QList<QMetaObject::Connection> connections;//用于监控该对象的连接
    QObject* obj;
};
typedef std::shared_ptr<ObjectData> ObjectDataPtr;
typedef QHash<ObjectID,ObjectDataPtr> ObjectDataMap;

//客户端注册接口
class RemoteRegistrySourceImp:public RemoteRegistrySource
{
public:
    RemoteRegistrySourceImp(QROHost::Private* parent);
    virtual int registerChannel(QVariant cookie) override;
    virtual void unregisterChannel(int id) override;

    QROHost::Private* _P;
};

//客户端接口
class RemoteInterfaceSourceImp:public RemoteInterfaceSimpleSource{
public:
    RemoteInterfaceSourceImp(QROHost::Private* parent);

    virtual QByteArray initialUpdate() override;

    virtual bool occupyObject(quint32 target) override;
    virtual bool releaseObject() override;
    virtual void serverCall(int id, int method, QVariantList param,int sync) override;
    virtual void pushProperty(int id, int prop, QVariant value) override;
    virtual void pushParent(int target,int parent) override;
    virtual void clientCallFinished(int synch, QVariant ret, bool success) override;

    QROHost::Private* _P;
};

//客户端数据
struct RemoteClientChannel{
    ChannelID id;
    RemoteInterfaceSourceImp* channel;
    QROClient* client;
};

typedef std::shared_ptr<RemoteClientChannel> RemoteClientChannelPtr;
typedef std::map<ChannelID,RemoteClientChannelPtr> ChannelMap;

struct QROHost::Private{

    Private(QROHost* Q);

    ~Private();

    QPointer<QROHostDelegate> m_delegate;

    //属性更新队列
    PropertyModifyDataSet m_propUpdateQueue;

    //对象列表
    ObjectDataMap m_objectDataMap;

    //对象id列表
    QHash<QObject*,ObjectID> m_objectIdMap;

    //网络接口
    RemoteRegistrySourceImp* m_registerInterface;
    ChannelMap m_channels;
    QRemoteObjectHost* m_host;

    ObjectID objectIdGen = 0;
    ObjectID allocObjectID()
    {
        objectIdGen++;
        return objectIdGen;
    }

    ChannelID channelIdGen = 0;
    ChannelID allocChannelID(){
        channelIdGen++;
        return channelIdGen;
    }

    InvokeID invokeIdGen = 0;

    InvokeID allocInvokeID()
    {
        invokeIdGen++;
        return invokeIdGen;
    }

    QHash<InvokeID,QRemoteObject2::InvokeCallBack> callBackQueue;


    QROHost* _Q;

    //前端接口函数
    void onStart(QString url);

    void onRegisterObject(QObject* obj);
    void onUnregisterObject(QObject* obj);
    void onUpdateProperty();
    void onMarkPropertyModify(QObject *o, int index);
    void onActiveMethod(QObject* target, int method, QVariantList param,QRemoteObject2::InvokeCallBack callBack);
    void onPushProperty(QObject *target,int prop,QVariant value);
    void onPushParent(QObject *target,QObject* parent);
    void onOccupyObject(QObject* target);
    void onReleaseObject(QObject* target);


    //数据类型转换接口函数
    void valueToNet(QVariant& param);
    void valueFromNet(QVariant& param,int targetType);

    //属性接口函数
    void observeProperty(const QMetaObject* meta,ObjectData* data,QObject* target,int prop);
    void clearPropertyQueue(QList<ObjectID> obj);
    QVariantList packAllPropertyData();

    //树状结构接口函数
    void observerParent(const QMetaObject* meta,ObjectData* data,QObject* target);
    QVariantList packAllParentData();

    //权限接口函数
    //获取某个对象所属的客户端，返回0代表属于服务端
    ChannelID belongsTo(ObjectID obj);

    //网络接口函数
    int onRegisterChannel(QVariant cookie);
    void onUnregisterChannel(int id);

    QByteArray onInitialUpdate(RemoteInterfaceSourceImp* src);
    bool onOccupyObject(RemoteInterfaceSourceImp* src,quint32 target);
    bool onReleaseObject(RemoteInterfaceSourceImp* src);
    void onServerCall(RemoteInterfaceSourceImp* src,int id,int method,QVariantList param,int synch);
    void onPushProperty(RemoteInterfaceSourceImp* src,int id, int prop, QVariant value);
    void onPushParent(RemoteInterfaceSourceImp* src,int target,int parent);
    void onClientCallReady(RemoteInterfaceSourceImp* src,int sync,QVariant ret,bool success);
};


class QROClientPrivate{
public:
    int id;
    QVariant cookie;
};




